home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
ab20
/
hardware
/
amscsi.lzh
/
scsi.asm
< prev
next >
Wrap
Assembly Source File
|
1987-05-26
|
6KB
|
206 lines
; SCSI DRIVER - for AMSCSI hardware
; NCR 53C80 - SCSI ctrl chip
; Rich Frantz may 1987
;
; This routine should be called from a DOS handler
; it should be noted that all command data should be
; checked for validity before calling. Also I have
; not finished the error handling.
;------------------------------------------------------------
NCR equ $800001 ;SCSI ctrl chip
Iid equ $80 ;d7 = init
Tid equ $01 ;d1 = target
M250 equ $1E000 ;250 mSEC dly
U200 equ $64 ;200 uSEC dly
;-------------------------------------------------------------
; a0 = IO_DATA - MUST BE SETUP BY CALLER
; a6 = DEVICE POINTER - MUST BE SETUP BY CALLER
; a4 = SCSI buffer pointer
; a5 = unassigned
; d0 = IO_LENGTH ( in bytes) - MUST BE SETUP BY CALLER
; d4 = IO_OFFSET / 256
; d5 = unassigned
;-------------------------------------------------------------
ReadSCSI: ;read data from the SCSI
movem.l d4/d5/a4/a5,-(sp) ;save regs
bsr.s Build_CMD ;build the scsi cmd packet
move.b #$08,CMDBUF ;set cmd to read
bsr SELph ;select the target
ReadSCSI_End:
movem.l (sp)+,d4/d5/a4/a5 ;restore regs
rts ;return to caller
WriteSCSI: ;send data to the SCSI
movem.l d4/d5/a4/a5,-(sp) ;save regs
bsr.s Build_CMD ;build the scsi cmd packet
move.b #$0A,CMDBUF ;set cmd to write
bsr SELph ;do it
WriteSCSI_End:
movem.l (sp)+,d4/d5/a4/a5 ;restoer regs
rts ;return to caller
FormatSCSI:
movem.l d4/d5/a4/a5,-(sp) ;save the regs
move.w #$0400,CMDBUF ;note set the unit #
move.l #0,CMDBUF+2 ;clr the cmd packet
bsr SELph ;do it
FormatSCSI_End:
movem.l (sp)+,d4/d5/a4/a5 ;restore th regs
rts ; return to caller
Build_CMD: ;build the scsi cmd packet
move.l d0,d5 ;get the #bytes to transfere
asr.l #8,d5 ;shift 8 palces to get sectors
and.l #$FF,d5 ;must be less than 1 byte
asl.l #8,d5 ;move to upper byte in word
move.w d5,CMDBUF+4 ;place in packet
asr.l #8,d4 ;convert to sectors
and.l #$000FFFFF,d4 ;mask out L U #
move.l d4,CMDBUF ;place in packet
Unit_No: ; add the unit #
rts ;packet complete
SELph: ;select the target
move.b #0,NCR+2 ;clr NCR
move.b #0,NCR+4
move.b #0,NCR+8
ARB: move.b #Iid,NCR ;ld init I D
or.b #1,NCR+4 ;set ARB bit
NFREE: btst.b #6,NCR+2 ;check arib in proc.
beq NFREE ;wait
nop ;delay for bus settle
nop
nop
nop
btst.b #5,NCR+2 ;check lost arb
bne.s SELph ;try again
;
;check for higher priority
;
move.l #0,d5 ;lcr d5
move.b NCR,d5 ;load scsi data
sub.b #Iid,d5 ;sub our id
beq.s WIN ;if = we are the only bidder
sub.b #Iid,d5 ;sub again
bmi.s WIN ;if - we are the highest
bra.s SELph ;try again
WIN: btst.b #5,NCR+2 ;check lost arb bit
bne.s SELph ;if lost , retry
move.b #$0c,NCR+2 ;set SEL
nop ;delay
nop
nop
nop
move.b #Iid,NCR ;load init I D
or.b #Tid,NCR ;load target I D
move.b #5,NCR+2 ;set SEL & Data Bus
and.b #$FE,NCR+4 ;clr ARB
and.b #$F7,NCR+2 ;clr BSY
move.l #M250,d5 ;load timer
loop1: btst.b #6,NCR+8 ;test BSY
bne.s SLECT ;if busy , selected
subq #1,d5 ;dec timer
bne.s loop1 ;loop
move.b #0,NCR ;clr I D's
move.l #U200,d5 ;load timer
loop2: btst.b #6,NCR ;test BSY
bne.s SLECT ;if busy , selected
subq #1,d5 ;dec timer
bne.s loop2 ;loop
bra error ;selection failed
SLECT: and.b #$FB,NCR+2 ;clr SEL
; NextPhase
NextPhase: ;Check the SCSI bus phase
btst.b #7,NCR+8 ;check RESET
bne RSTph ;reset phase
btst.b #6,NCR+8 ;check BUSY
beq Done ;bus free
btst.b #3,NCR+8 ;check C/D
beq.s Dat ;data in/out phase
btst.b #4,NCR+8 ;check MSG
bne.s Message ;Message in/out phase
btst.b #2,NCR+8 ;check I/O
bne.s STATph ;stat phase
bra.s CMDph ;command phase
Message: ;check to see if it is message in or out
btst.b #2,NCR+8 ;check I/O
bne.s MSGINph
bra.s MSGOUTph
Dat: ;check to see if it is data in or out
btst.b #2,NCR+8 ;check I/O
bne.s RDATph
bra.s SDATph
Done: ;did we end normally ?
cmp.b #$FF,STAT ;did we get a status byte
bne.s Return
error: move #1,d5 ;set error code *********************
Return: rts
RSTph: ;reset phase
bra.s Done ;done
CMDph: ;send command
move.l #CMDBUF,a4 ;set the cmd buffer add
move.b #$02,NCR+6 ;set TCR to command phase
bra.s Send ;send the command
STATph: ;get status byte
move.l #STAT,a4 ;set the stat buffer add
move.b #$03,NCR+6 ;set TCR to status phase
bra.s Rec ;get the stat
MSGINph: ;get message from target
move.l #MSGINBUF,a4 ;set the message in buffer add
move.b #$07,NCR+6 ;set TCR to message in phase
bra.s Rec ;get the message
MSGOUTph: ;send message to target
bra NextPhase ;error try again
RDATph: ;receive data fron target
move.l #DATBUF,a4 ;set the data buffer add
move.b #$01,NCR+6 ;set TCR to receive data
bra.s Rec ;get the data
SDATph: ;send data to target
move.l #DATBUF,a4 ;set the data buffer add
move.b #$00,NCR+6 ;set TCR to send data
Send: ;send x characters to the target
move.b (a4)+,NCR ;set the byte
Send1: btst.b #5,NCR+8 ;test for REQ
beq.s Send1 ;wait for REQ
or.b #$10,NCR+2 ;set ACK
Send2: btst.b #5,NCR+8 ;test REQ
bne.s Send2 ;wait for /REQ
andi.b #$EF,NCR+2 ;clr ACK
btst.b #3,NCR+10 ;test pahse match
bne.s Send
bra NextPhase
Rec: ;receive x characters form the target
Rec1: btst.b #5,NCR+8 ;test REQ
beq.s Rec1 ;wait for REQ
move.b NCR,(a4)+ ;get byte from target
or.b #$10,NCR+2 ;set ACK
Rec2: btst.b #5,NCR+10 ;test REQ
bne.s Rec2 ;wait for /REQ
andi.b #$EF,NCR+2
btst.b #3,NCR+10 ;test for phase match
bne.s Rec
bra NextPhase
CMDBUF dc.b $0A,$00,$00,$00,$01,$00 ;command string (write 1 block)
STAT ds.b $01 ;status word
MSGINBUF ds.b $04 ;message buffer
DATBUF ds.b $200 ;data buffer
end